package com.stylefeng.guns.rest.modular.websocket;


import com.alibaba.dubbo.config.annotation.Reference;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.stylefeng.guns.api.websocket.WebSocketAPI;
import com.stylefeng.guns.rest.SpringContext;
import com.stylefeng.guns.rest.common.persistence.dao.UserMapper;
import com.stylefeng.guns.rest.modular.websocket.vo.ChatServiceAPI;
import com.stylefeng.guns.api.websocket.vo.MessageVO;
import com.stylefeng.guns.rest.modular.websocket.vo.ResponseVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: websocket的具体实现类
 * 使用springboot的唯一区别是要@Component声明下，而使用独立容器是由容器自己管理websocket的，
 * 但在springboot中连容器都是spring管理的。
虽然@Component默认是单例模式的，但springboot还是会为每个websocket连接初始化一个bean，
所以可以用一个静态set保存起来。
 */
@ServerEndpoint("/webSocket/chat/{roomName}/{nickname}")
@Component
public class WebSocketController {
    @Autowired
    private SpringContext springContext;

    // 使用map来收集session，key为roomName，value为同一个房间的用户集合
    // concurrentMap的key不存在时报错，不是返回null
    private static final Map<String, Set<Session>> rooms = new ConcurrentHashMap();

    private String nickname;

    //统计当前在线人数
    private  int online_num = 0;

    @OnOpen
    public void connect(@PathParam("roomName") String roomName, @PathParam("nickname") String nickname, Session session) throws Exception {
        // 将session按照房间名来存储，将各个房间的用户隔离
        if (!rooms.containsKey(roomName)) {
            // 房间不存在时，创建房间
            Set<Session> room = new HashSet<>();
            // 添加用户
            room.add(session);
            rooms.put(roomName, room);
        } else {
            // 房间已存在，直接添加用户到相应的房间
            rooms.get(roomName).add(session);
            online_num = (rooms.get(roomName).size())/2;
//            addOnlineCount();
            String fromUser = "server";
            String msg = nickname+"进入了房间";
            MessageVO message = packageData(fromUser,msg,online_num);
            ObjectMapper mapper = new ObjectMapper();
            String json="";
            try {
                json = mapper.writeValueAsString(message);

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            broadcast(roomName,json);
            //更新观看人数
            WebSocketAPI webSocketAPI = (WebSocketAPI) SpringContext.getBean(WebSocketAPI.class);
            int i = webSocketAPI.updateOnlineNum(online_num, roomName);
            System.out.println(i+"*************");

//            session.getAsyncRemote().sendText(nickname+"进入了房间");
        }
        System.out.println(nickname + "has connected!");
    }

    @OnClose
    public void disConnect(@PathParam("roomName") String roomName, @PathParam("nickname") String nickname, Session session) {
        rooms.get(roomName).remove(session);
//        subOnlineCount();
        online_num = rooms.get(roomName).size()/2;
        String fromUser = "server";
        String msg = nickname+"退出了房间";
        MessageVO message = packageData(fromUser,msg,online_num);
        ObjectMapper mapper = new ObjectMapper();
        String json="";
        try {
            json = mapper.writeValueAsString(message);

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        broadcast(roomName,json);
        //更新观看人数
        WebSocketAPI webSocketAPI = (WebSocketAPI) SpringContext.getBean(WebSocketAPI.class);
        int i = webSocketAPI.updateOnlineNum(online_num, roomName);
        System.out.println(nickname + "已退出直播间！");
    }

    @OnMessage
    public void receiveMsg(@PathParam("roomName") String roomName, @PathParam("nickname") String nickname,
                           String msg, Session session) throws Exception {

        //创建时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date date = new Date();
        String time = simpleDateFormat.format(date);
        String message;
        //可以在此保存数据到数据库
        MessageVO messageVO = new MessageVO();
        UUID uuid = UUID.randomUUID();
        String str = uuid.toString();
        String uuidStr = str.replace("-", "");
        messageVO.setId(uuidStr);
        messageVO.setFromUser(nickname);
        messageVO.setMsg(msg);
        messageVO.setTime(time);

        ChatServiceAPI chatServiceAPI = (ChatServiceAPI) SpringContext.getBean(ChatServiceAPI.class);
        chatServiceAPI.saveDemo(messageVO);

        MessageVO mes = new MessageVO();
        for (Session session1 : rooms.get(roomName)) {
            //判断是否发送给自己
            if (session1.equals(session)) {
                //发送给自己
                online_num = rooms.get(roomName).size();
                String fromUser = nickname;
                mes = packageData(fromUser,msg,online_num);
            } else {
                //发送给别人
                online_num = rooms.get(roomName).size();
                String fromUser = nickname;
                mes = packageData(fromUser,msg,online_num);
            }
            //发送
            ObjectMapper mapper = new ObjectMapper();
            String json="";
            try {
                json = mapper.writeValueAsString(mes);

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            session1.getAsyncRemote().sendText(json);

        }
    }

    /**
     * 封装数据
     */
    public MessageVO packageData(String fromUser,String msg,int online_num){
        //创建时间
        SimpleDateFormat simple = new SimpleDateFormat("HH:mm");
        Date date = new Date();
        String time = simple.format(date);
        //uuid
        UUID uuid = UUID.randomUUID();
        String str = uuid.toString();
        String uuidStr = str.replace("-", "");
        //转换vo
        MessageVO messageVO = new MessageVO();
        messageVO.setId(uuidStr);
        messageVO.setFromUser(fromUser);
        messageVO.setMsg(msg);
        messageVO.setTime(time);
        messageVO.setOnlineNum(online_num);

        return  messageVO;
    }

    /**
     * 群发自定义消息
     */
    public void broadcast(String roomName,String message) {
//        for (String key : rooms.keySet()) {
            //同步异步说明参考：http://blog.csdn.net/who_is_xiaoming/article/details/53287691
            //this.session.getBasicRemote().sendText(message);
            for (Session sess : rooms.get(roomName)) {
                    sess.getAsyncRemote().sendText(message);
//                sess.getAsyncRemote().sendObject(message);//异步发送消息.
            }

    }
}